﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.FriendlyException;
using System.Globalization;
using System.Text;
using Admin.NET.Core;

namespace Admin.NET.Application
{
    /// <summary>
    /// 单据号生成帮助类
    /// </summary>
    public class SerialUtil
    {

        private readonly static object _lockTest = new();
        private readonly static object _lockPublic = new();
        /// <summary>
        /// 生成编号/单据号
        /// </summary>
        /// <param name="SerialType"></param>
        /// <returns></returns>
        public static async Task<string> GetSerial(EnumSerialType SerialType)
        {
            switch (SerialType)
            {
                case EnumSerialType.测试编号:
                    lock (_lockTest)
                    {
                        return GetSerialDetails(SerialType).Result;
                    };
                default:
                    lock (_lockPublic)
                    {//为了避免多线程出现编号一致的情况，加上锁，此处为公共锁，只用于不频繁生成编号的，若需要频繁生成，请参考上面Test设置单独锁
                        return GetSerialDetails(SerialType).Result;
                    }
            }

        }
        /// <summary>
        /// 生成编号/单据号
        /// </summary>
        /// <param name="SerialType"></param>
        /// <returns></returns>
        private static async Task<string> GetSerialDetails(EnumSerialType SerialType)
        {
            // 泛型仓储
            var repositoryBaseSerialRuleDetail = Db.GetRepository<BaseSerialRuleDetail>();
            var repositoryBaseSerialSN = Db.GetRepository<BaseSerialSN>();

            var lst = repositoryBaseSerialRuleDetail.Where(x => x.SerialType == (int)SerialType)
                .OrderBy(x => x.ItemNo).ToList();

            string[] strs = new string[lst.Count];

            BaseSerialSN sl = new BaseSerialSN();
            for (int i = 0; i < lst.Count; i++)
            {
                if (lst[i].SourceType.ToUpper() == EnumSerialSourceType.UD.ToString())
                {
                    strs[i] = lst[i].UserDefine ?? string.Empty;//如果数据源是自定义，则取自定义字段
                }
                if (lst[i].SourceType.ToUpper() == EnumSerialSourceType.Y4.ToString())
                {
                    strs[i] = DateTime.Now.Year.ToString();
                }
                if (lst[i].SourceType.ToUpper() == EnumSerialSourceType.Y2.ToString())
                {
                    strs[i] = DateTime.Now.Year.ToString().Substring(2, 2);
                }
                if (lst[i].SourceType.ToUpper() == EnumSerialSourceType.M2.ToString())
                {
                    strs[i] = DateTime.Now.Month.ToString("00");
                }
                if (lst[i].SourceType.ToUpper() == EnumSerialSourceType.D2.ToString())
                {
                    strs[i] = DateTime.Now.Day.ToString("00");

                }
                if (lst[i].SourceType.ToUpper() == EnumSerialSourceType.W2.ToString())
                {
                    GregorianCalendar gc = new GregorianCalendar();
                    int week = gc.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
                    strs[i] = "W" + week.ToString();

                }
                if (lst[i].SourceType.ToUpper() == EnumSerialSourceType.SN.ToString())
                {
                    int cout = lst[i].SerialLength;
                    string c = string.Empty;
                    for (int j = 0; j < cout; j++)
                    {
                        c += "0";
                    }
                    try
                    {
                        if (lst[i].GetData.HasValue && lst[i].GetData == 1)
                        {
                            var sn = repositoryBaseSerialSN.Where(x => x.SerialType == lst[i].SerialType && x.CurrentDate == DateTime.Now.Date)
                                            .OrderByDescending(x => x.Sn).First();
                            sl.Sn = sn.Sn + 1;
                        }
                        else
                        {

                            var sn = repositoryBaseSerialSN.Where(x => x.SerialType == lst[i].SerialType)
                                            .OrderByDescending(x => x.Sn).First();
                            sl.Sn = sn.Sn + 1;
                        }

                        strs[i] = sl.Sn.ToString(c);
                    }
                    catch (Exception ex)
                    {
                        strs[i] = 1.ToString(c);
                        sl.Sn = 1;
                    }
                    sl.CurrentDate = DateTime.Now.Date;
                    sl.SerialType = lst[i].SerialType;
                }
            }

            StringBuilder BaseSerialSN = new StringBuilder();
            foreach (var item in strs)
            {
                BaseSerialSN.Append(item.ToString());
            }
            await sl.InsertAsync();
            //await repositoryBaseSerialSN.Add(sl);
            //edm.SaveChanges();

            if (string.IsNullOrEmpty(BaseSerialSN.ToString()))
            {
                throw Oops.Oh("生成的编号为空");
            }

            return BaseSerialSN.ToString();
        }
    }
}
